package com.tim.third.utils;


import org.apache.commons.lang3.RandomUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.comparator.Comparators;

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.LockSupport;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.function.UnaryOperator;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;

/**
 * @Description:
 * @Version 1.0, 2021/6/11
 * @Author Tim
 */
public class JdkUtils {
    public static void main(String[] args) {

    }
    
    public static void utils() throws Exception {
        Function.identity();// e->e

        Collections.emptyList();

        Arrays.asList("");

        Objects.isNull(null);

        Files.copy((Path)null,(Path)null);

        Paths.get("");

        Math.abs(-1);
    }
    
    public static void usefulClass() throws Exception{
    	// sleep 10s
    	TimeUnit.SECONDS.sleep(10);
    	// 加锁；等待100ms
    	LockSupport.parkNanos(100*1000*1000);
    	LockSupport.unpark(Thread.currentThread());
    	// 执行js代码
        ScriptEngineManager mgr=new ScriptEngineManager();
        ScriptEngine engine=mgr.getEngineByName("javascript");
        Object obj = engine.eval("1+1");
    	
    }


    
    public static void collections(){
        List<Integer> list = Arrays.asList(1,3,2,4,1,6,72,3,4);
        // 排序
        Collections.sort(list);
        // 二分查找
        Collections.binarySearch(list, 5);
        // 倒置
        Collections.reverse(list);
        // 倒序
        Collections.reverseOrder();
        Collections.reverseOrder(Comparator.<Integer>naturalOrder());
        Comparator.<Integer>naturalOrder().reversed();
        Comparators.<Integer>nullsHigh();
        // 乱序
        Collections.shuffle(list);
        // 交换
        Collections.swap(list, 1, 5);
        // 填充
        Collections.fill(list, 1);
        // 复制
        Collections.copy(list, new ArrayList<>(20));
        // 最值
        Collections.min(list);
        Collections.max(list);
        // 滚动
        Collections.rotate(list, 2);
        // 替换
        Collections.replaceAll(list, 1, 123);
        // 子串位置
        Collections.indexOfSubList(list, Arrays.asList(1,2));
        Collections.lastIndexOfSubList(list, Arrays.asList(1,2));
        // 包装集合：不可变、同步、类型校验
        Collections.unmodifiableCollection(list);
        Collections.synchronizedCollection(list);
        Collections.checkedCollection(list, Integer.class);
        // 新集合
        Collections.emptyList();
        Collections.singletonList(1);
        Collections.nCopies(10, "copy");
        // 次数
        Collections.frequency(list, 1);
        // 不相交
        Collections.disjoint(list, Collections.singleton(2));
        // 插入数组元素
        Collections.addAll(list, 2,3,4);

    }

    
    public static void arrays(){
        // 排序
        Arrays.sort(new int[]{1,7,4,2});
        Arrays.parallelSort(new int[]{1,7,4,2});
        // 并行处理？
        Arrays.parallelPrefix(new Integer[]{1,7,4,2}, BinaryOperator.maxBy(Comparator.<Integer>naturalOrder()));
        // 二分查找
        Arrays.binarySearch(new Integer[]{1,7,4,2}, 4);
        // 相等
        Arrays.equals(new Integer[]{1,7,4,2}, new Integer[]{1,7,4,2});
        // 填充、设置
        Arrays.fill(new int[10], 13);
        Arrays.setAll(new int[10], t->t);
        Arrays.parallelSetAll(new int[10], t->t);
        // 复制
        Arrays.copyOf(new Integer[]{1,7,4,2}, 3);
        Arrays.copyOfRange(new Integer[]{1,7,4,2}, 1, 3);
        System.arraycopy(new Integer[]{1,7,4,2}, 0, new int[10], 0, 4);
        // 集合、流
        Arrays.asList(1,2,3);
        Arrays.stream(new Integer[]{1,7,4,2}, 1, 3);
        // 转字符串
        Arrays.toString(new Integer[]{1,7,4,2});
        // 分隔
        Arrays.spliterator(Arrays.copyOf(new int[10], 6));
    }

    
    public static void objects(){
        // 相等
        Objects.equals(1, 2);
        Objects.deepEquals(1, 1);
        // 空判定
        Objects.nonNull(null);
        Objects.isNull(null);
        Objects.requireNonNull(null, "err msg");
        // 转字符串、比较
        Objects.toString(null, "hello");
        Objects.compare(1, 2, Comparator.naturalOrder());
    }
    
    public static void files() throws Exception{
        Path PATH = Paths.get("");
        // 输入输出流
        Files.newInputStream(PATH);
        Files.newOutputStream(PATH);
        Files.newDirectoryStream(PATH, "*.java");// 文件夹
        // channel方式
        Files.newByteChannel(PATH);
        // reader、writer
        Files.newBufferedReader(PATH, StandardCharsets.UTF_8);
        Files.newBufferedWriter(PATH, StandardCharsets.UTF_8);
        // 创建文件/文件夹
        Files.createFile(PATH);
        Files.createDirectory(PATH);
        Files.createDirectories(PATH);// 创建不存在的父级
        Files.createTempFile(PATH, "hello", ".java");
        Files.createTempDirectory(PATH, "tempDir");
        // 删除
        Files.deleteIfExists(PATH);
        // 复制、移动
        Files.copy(Paths.get("src"), Paths.get("dest"));
        Files.move(Paths.get("src"), Paths.get("dest"));
        // 判定 Files.is*
        Files.isDirectory(PATH);
        Files.isReadable(PATH);
        // 大小
        Files.size(PATH);
        // 存在
        Files.exists(PATH);
        // 遍历
        Files.walkFileTree(PATH, null);
        // 读写
        Files.readAllLines(PATH, StandardCharsets.UTF_8);
        String content = Files.lines(PATH, StandardCharsets.UTF_8)
                .collect(Collectors.joining("\n"));
        Files.write(PATH, Collections.emptyList(),StandardCharsets.UTF_8);
        // 显示文件
        Files.list(PATH);
        Files.find(PATH, 3, (path,attrs)->path.endsWith(".java")&&attrs.size()>1024)
                .forEach(System.out::println);;


    }
    
    public static void paths(){
        Paths.get("");
    }

    public static void comparator(){
        // 比较器；正序、倒序
        Comparator.<Integer>naturalOrder();
        Comparator.<Integer>reverseOrder();
        // 多级比较器
        Comparator.<Integer>naturalOrder()
                .thenComparingInt(num->num.intValue());
        // 空值处理
        Comparator.nullsFirst(Comparator.<Integer>naturalOrder());
        // 属性比较
        Comparator.<Integer>comparingInt(Integer::intValue);


    }

    
    public static void streamCollectors(){
        Stream<String> stream=Arrays.asList("a","ab","abc").stream();
        // 连接为字符
        String str=stream.collect(Collectors.joining(","));
        // 转List、Set、Map
        List<String> list = stream.collect(Collectors.toList());
        Set<String> set = stream.collect(Collectors.toSet());
        Map<Integer, String> map = stream.collect(Collectors.toMap(t->t.length(), Function.identity(), BinaryOperator.maxBy(Comparator.<String>naturalOrder())));
        ConcurrentMap<Integer, String> ccMap = stream.collect(Collectors.toConcurrentMap(t->t.length(), Function.identity()));
        // 按属性维度分组
        Map<Integer, List<String>> mapList = stream.collect(Collectors.groupingBy(String::length));
        ConcurrentMap<Integer, List<String>> ccMapList = stream.collect(Collectors.groupingByConcurrent(String::length));
        // 分区
        Map<Boolean, Set<String>> partitionMapSet = stream.collect(Collectors.partitioningBy(item->item.length()>5, Collectors.toSet()));
        // 多级映射；groupingBy、partitioningBy
        Map<Integer, Set<String>> mapSet = stream.collect(
                Collectors.groupingBy(String::length, Collectors.mapping(String::toLowerCase, Collectors.toSet()))
        );
        // 追加操作；finisher返回结果
        list = stream.collect(Collectors.collectingAndThen(Collectors.toList(), Collections::unmodifiableList));
        // 统计操作
        Long num = stream.collect(Collectors.counting());
        String max = stream.collect(Collectors.maxBy(Comparator.naturalOrder())).orElse("");
        String min = stream.collect(Collectors.minBy(Comparator.naturalOrder())).orElse("");
        Integer sum = stream.collect(Collectors.summingInt(String::length));
        Double avg = stream.collect(Collectors.averagingInt(String::length));
        IntSummaryStatistics statistics = stream.collect(Collectors.summarizingInt(String::length));
        // reducing；分解、归纳
        Integer sum2 = stream.collect(Collectors.reducing(0, String::length, Integer::sum));


    }

    /**
     * Stream操作类型：中间操作、结束操作；调用结束操作时，执行中间操作。
     * 操作类型描述：
     *  stateful；有状态，拿到全部元素才能进行下一步，如：sort、distinct
     *  short-circuiting；短路，立即输出，无限流输出有限结果；任意元素匹配即可得出结果，如：limit、findAny
     */
    
    public static void stream(){
        /*************创建***************/
        // 无限流
        Stream<String> infiniteStream;
        infiniteStream = Stream.generate(UUID::randomUUID).map(UUID::toString);
        infiniteStream = Stream.iterate("seed", UnaryOperator.identity());
        // 有限流
        Stream<String> stream;
        stream = Stream.empty();
        stream = Stream.of("hello", "world");
        // 数值流
        IntStream intStream = IntStream.generate(RandomUtils::nextInt);
        intStream = new Random().ints(100, 20, 200);
        // 拼接
        stream = Stream.concat(infiniteStream, stream);

        /*************中间操作***************/
        stream.filter(Objects::nonNull)// 过滤
                .map(Function.identity())// 映射
                .mapToInt(String::length)// 映射为IntStream
                .mapToObj(Integer::toHexString)// IntStream、LongStream、DoubleStream
                .flatMap(item->Stream.of(item.split("")))// 元素展开后拼接，一对多。List<List<String>>转List<String>
                .distinct()// 唯一
                .sorted(Comparator.naturalOrder())// 排序
                .peek(System.out::println)// 返回原stream，额外执行操作。调试用
                .limit(20)// 限制数量
                .skip(5);// 跳过
        // 数值流
        intStream.asLongStream()// 转换
                .parallel().sequential()// 并行串行
                .boxed();// 包装
        /*************结束操作***************/
        // 无返回操作
        stream.forEach(System.out::println);// 不保证顺序
        stream.forEachOrdered(System.out::println);
        // 转数组
        Object[] objs = stream.toArray();
        String[] strs = stream.toArray(String[]::new);
        // 归纳
        String str = stream.reduce(String::concat).orElse("");
        str = stream.reduce("", String::concat);
        str = stream.collect(Collectors.joining());
        // 统计
        str = stream.max(Comparator.naturalOrder()).orElse("");
        str = stream.min(Comparator.naturalOrder()).orElse("");
        long num = stream.count();
        // 数值统计
        num = intStream.sum();
        double avg = intStream.average().orElse(0);
        IntSummaryStatistics statistics = intStream.summaryStatistics();

        // 搜索
        str = stream.findFirst().orElse("");
        str = stream.findAny().orElse("");
        // 匹配
        boolean bool = stream.anyMatch(StringUtils::isNotBlank);
        bool = stream.noneMatch(StringUtils::isNotBlank);
        bool = stream.allMatch(StringUtils::isNotBlank);
    }

    
    public static void math(){
        double d = Math.random();

        /*************数值运算***************/
        Math.ceil(1.7);// 向上取整
        Math.floor(1.3);// 向下取整
        Math.floorDiv(2, 3);//
        Math.floorMod(13, 4);//
        Math.round(1.4);// 四舍五入
        Math.rint(1.5);// 四舍五入，.5时取偶数值
        Math.abs(-3);// 绝对值
        Math.max(1,3);
        Math.min(2,4);

        /*************溢出时抛异常***************/
        Math.toIntExact(100L);// 转int

        Math.addExact(1, 1);// 加
        Math.subtractExact(2,4);// 减
        Math.multiplyExact(3,5);// 乘
        Math.incrementExact(4);// 增1
        Math.decrementExact(5);// 减1
        Math.negateExact(2);// 取反

        /*************幂运算***************/
        Math.pow(2, 4);// 2的4次方

        Math.exp(2);// 欧拉数的n次方
        Math.log(Math.E);// 欧拉数的幂次
        Math.log10(10);// 10的幂次
        Math.sqrt(4);// 平方根
        Math.cbrt(8);// 立方根

        /*************三角函数***************/
        Math.sin(30);// 正弦
        Math.asin(0.5);// 正弦角
        Math.cos(30);// 余弦
        Math.acos(0.5);
        Math.tan(2);// 正切
        Math.atan(2);
        Math.toDegrees(Math.PI);// 角度
        Math.toRadians(180);// 弧度

    }

    
    public static void mathCalculate(){
        Math.floorDiv(2, 3);//
        Math.floorMod(13, 4);//

        // 向上取整；
        System.out.println("向上取整");
        System.out.println(Math.ceil(1.7));// 2
        System.out.println(Math.ceil(-1.7));// -1
        System.out.println(Math.ceil(2.1));// 3
        System.out.println(Math.ceil(-2.1));// -2
        // 向下取整；
        System.out.println("向下取整");
        System.out.println(Math.floor(1.3));// 1
        System.out.println(Math.floor(-1.3));// -2
        System.out.println(Math.floor(2.7));// 2
        System.out.println(Math.floor(-2.7));// -3
        // 先求商再向下取整
        System.out.println("先求商再向下取整");
        System.out.println(Math.floorDiv(3,4));// 0
        System.out.println(Math.floorDiv(-3,4));// -1
        System.out.println(Math.floorDiv(3,-4));// -1
        System.out.println(Math.floorDiv(-3,-4));// 0
        // 先取模再向下取整；floorMod(a,b)=a-floorDiv(a,b)*b
        System.out.println("先取模再向下取整；floorMod(a,b)=a-floorDiv(a,b)*b");
        System.out.println(Math.floorMod(3,4));// 3
        System.out.println(Math.floorMod(-3,4));// 1
        System.out.println(Math.floorMod(3,-4));// -1
        System.out.println(Math.floorMod(-3,-4));// -3
        // 四舍五入
        System.out.println("四舍五入");
        System.out.println(Math.round(1.4));// 1
        System.out.println(Math.round(-1.4));// -1
        System.out.println(Math.round(2.6));// 3
        System.out.println(Math.round(-2.6));// -3
        System.out.println(Math.round(1.5));// 2
        System.out.println(Math.round(-1.5));// -1
        System.out.println(Math.round(2.5));// 3
        System.out.println(Math.round(-2.5));// -2
        // 四舍五入，.5时取偶数值
        System.out.println("四舍五入，.5时取偶数值");
        System.out.println(Math.rint(1.4));// 1
        System.out.println(Math.rint(-1.4));// -1
        System.out.println(Math.rint(2.6));// 3
        System.out.println(Math.rint(-2.6));// -3
        System.out.println(Math.rint(1.5));// 2
        System.out.println(Math.rint(-1.5));// -2
        System.out.println(Math.rint(2.5));// 2
        System.out.println(Math.rint(-2.5));// -2

    }
}
